﻿/********************************************************************************
 * Developed by Phil Tyler (http://www.laidbackcoder.co.uk)
 * 
 * Cryptosolic is Licensed under the GNU Lesser General Public License (LGPL)
 * http://cryptosolic.codeplex.com/license
 * *****************************************************************************/
using Cryptosolic.Security.Encryption.Symmetric;
using NUnit.Framework;
using System.Text;

namespace Cryptosolic.Security.Tests
{
    /// <summary>
    /// Base Methods to Test an Encryption Algorithm
    /// </summary>
    public class SymmetricEncryptionTestsBase
    {
    	public string key = "{my.Very_$ecure,Test-K3y!]";
        public ISymmetricEncryptionAlgorithm encryptionAlgorithm;

        public void assert_EncryptData_OutputEncryptedDataDifferentFromInput()
        {
            byte[] initialValue = Encoding.UTF8.GetBytes("this.is.a.test");
            byte[] actual = encryptionAlgorithm.EncryptData(initialValue, key,  encryptionAlgorithm.GenerateRandomIV()).ToBytes();

            CollectionAssert.AreNotEqual(initialValue, actual);
        }


        public void assert_EncryptData_OutputEncryptedDataRepeatable()
        {
            byte[] initialValue = Encoding.UTF8.GetBytes("this.is.a.test");
            
            byte[] iV =  encryptionAlgorithm.GenerateRandomIV();

            byte[] actual1 = encryptionAlgorithm.EncryptData(initialValue, key, iV).ToBytes();
            byte[] actual2 = encryptionAlgorithm.EncryptData(initialValue, key, iV).ToBytes();

            CollectionAssert.AreEqual(actual1, actual2);
        }


        public void assert_EncryptData_OutputEncryptedDataDifferentWithTwoDifferentInputs()
        {
            byte[] initialValue1 = Encoding.UTF8.GetBytes("this.is.a.test");
            byte[] initialValue2 = Encoding.UTF8.GetBytes("this.is.b.test");
            
            byte[] iV =  encryptionAlgorithm.GenerateRandomIV();
            
            string actual1 = encryptionAlgorithm.EncryptData(initialValue1, key, iV).ToHex();
            string actual2 = encryptionAlgorithm.EncryptData(initialValue2, key, iV).ToHex();

            Assert.AreNotEqual(actual1, actual2);
        }

        public void assert_DecryptData_SuccessfullyDecryptData()
        {
        	//I Guess this could actually be an Integration Test as the initial value was created
            //using the EncryptData() Method. 
            
            string expected = "this.is.a.test";
            
            byte[] iV =  encryptionAlgorithm.GenerateRandomIV();
            
            string encryptedData = encryptionAlgorithm.EncryptData(expected, key, iV).ToString();
            string actual = encryptionAlgorithm.DecryptData(encryptedData, key, iV).ToString();

            Assert.AreEqual(expected, actual);
        }
        
        public void assert_DecryptData_UnsuccessfullyDecryptDataWithTwoDifferentIVs()
        {
        	//I Guess this could actually be an Integration Test as the initial value was created
            //using the EncryptData() Method. 
            
            Assert.Throws<Cryptosolic.Security.Encryption.Exceptions.DecryptionFailureException>(() => 
            {        
	            string data = "this.is.a.test";
	            
	            byte[] iv1 = encryptionAlgorithm.GenerateRandomIV();
	            byte[] iv2 = encryptionAlgorithm.GenerateRandomIV();
	            
	            string encryptedData = encryptionAlgorithm.EncryptData(data, key, iv1).ToString();
	            string actual = encryptionAlgorithm.DecryptData(encryptedData, key, iv2).ToString();
            });
        }
        
        public void assert_DecryptData_UnsuccessfullyDecryptDataWithTwoDifferentKeys()
        {
        	//I Guess this could actually be an Integration Test as the initial value was created
            //using the EncryptData() Method. 
            
            Assert.Throws<Cryptosolic.Security.Encryption.Exceptions.DecryptionFailureException>(() => 
            {        
	            string data = "this.is.a.test";
	            
	            byte[] iv = encryptionAlgorithm.GenerateRandomIV();
	            
	            string key1 = "abc";
	            string key2 = "xyz";
	            
	            string encryptedData = encryptionAlgorithm.EncryptData(data, key1, iv).ToString();
	            string actual = encryptionAlgorithm.DecryptData(encryptedData, key2, iv).ToString();
            });
        }
        
        public void assert_EncryptData_OutputEncryptedDataDifferentWhenUsingSaltWithKey()
        {
        	byte[] initialValue = Encoding.UTF8.GetBytes("this.is.a.test");
            
            byte[] iV =  encryptionAlgorithm.GenerateRandomIV();
            
            string salt = "ThisIsASalt";
            
            string actual1 = encryptionAlgorithm.EncryptData(initialValue, key, salt, iV).ToHex();
            string actual2 = encryptionAlgorithm.EncryptData(initialValue, key, iV).ToHex();

            Assert.AreNotEqual(actual1, actual2);
        }
    }
}
